package com.cloudfun.msglisten.ws.haier;

import com.alibaba.fastjson.JSONObject;
import com.cloudfun.msglisten.common.model.dto.dingtalk.TextContent;
import com.cloudfun.msglisten.common.model.haier.HaierBaseReqDTO;
import com.cloudfun.msglisten.service.DingTalkService;
import com.cloudfun.msglisten.ws.haier.config.HaierWsProperties;
import com.google.common.util.concurrent.RateLimiter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by Huqin on 2019/12/17
 */
@Slf4j
@Component
public class HaierWsClientHeartBeatService implements DisposableBean, InitializingBean {

    @Autowired
    private HaierWsClient haierWsClient;

    @Autowired
    private HaierWsProperties haierWsProperties;

    @Autowired
    private DingTalkService dingTalkService;

    private final HaierBaseReqDTO<String> heatBeatMsg = new HaierBaseReqDTO<>("keepAlive", null);

    private volatile ScheduledExecutorService executorService;

    // 最新收消息时间,心跳发消息时做时间间隔计算
    private final AtomicLong lastReceiveTime = new AtomicLong();

    //两分钟允许通知一次,防止频率过高
    private RateLimiter rateLimiter = RateLimiter.create(1/120.0D);

    @Override
    public void afterPropertiesSet() throws Exception {
        if (executorService == null || executorService.isShutdown()) {
            executorService = Executors.newScheduledThreadPool(1);
        }
        executorService.scheduleAtFixedRate(heatBeatTask(), haierWsProperties.getHeartBeat().getInitDelay(),
                haierWsProperties.getHeartBeat().getPeriod(), TimeUnit.SECONDS);
    }

    @Override
    public void destroy() throws Exception {
        if (!executorService.isShutdown()) {
            executorService.shutdown();
        }
    }

    /**
     * 更新最新收消息时间
     */
    public void updateLastReceiveTime() {
        lastReceiveTime.set(System.currentTimeMillis());
    }

    private Runnable heatBeatTask() {
        return () -> {
            // 距离上一次交互的时间间距
            long interval = (System.currentTimeMillis() - lastReceiveTime.get()) / 1000;
            // 超过 50s后 发送一次心跳 检测是否还有连接
            if (interval > haierWsProperties.getHeartBeat().getInterval()) {
                boolean heatBeatSuccess = haierWsClient.sendCommand(JSONObject.toJSONString(heatBeatMsg));
                if (heatBeatSuccess) {
                    log.debug("海尔websocket心跳任务执行，心跳发送成功");
                    if (rateLimiter.tryAcquire()) {
                        dingTalkService.sendMessage(new TextContent("海尔websocket心跳任务执行成功，请关注是否有数据推送"));
                    }
                } else {
                    log.debug("海尔websocket心跳任务执行，心跳发送失败");
                    dingTalkService.sendMessage(new TextContent("海尔websocket心跳发送失败"));
                }
            }
        };
    }
}
